﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;

namespace Xceed.Silverlight.DataGrid
{
  internal delegate void XceedRoutedEventHandler( object sender, XceedRoutedEventArgs args );

  [DebuggerStepThrough]
  internal sealed class XceedEventHelper
  {
    #region Constructor

    internal XceedEventHelper( IXceedRoutedEventElement element )
    {
      if( element == null )
        throw new ArgumentNullException( "element" );

      m_element = element;
    }

    #endregion

    internal void RaiseEvent( XceedRoutedEvent routedEvent, XceedRoutedEventArgs args )
    {
      if( !object.ReferenceEquals( args.OriginalSource, m_element ) )
        throw new DataGridInternalException();

      IXceedRoutedEventElement currentHandledObject = m_element;
      LinkedList<XceedRoutedEventHandler> handlers;
      while( currentHandledObject != null )
      {
        if( currentHandledObject.EventManager.m_handlers.TryGetValue( routedEvent, out handlers ) )
        {
          foreach( XceedRoutedEventHandler currentHandler in handlers )
          {
            currentHandler( currentHandledObject, args );
          }
        }
        currentHandledObject = XceedEventHelper.GetParent( currentHandledObject );
      }
    }

    internal void AddHandler( XceedRoutedEvent routedEvent, XceedRoutedEventHandler handler )
    {
      LinkedList<XceedRoutedEventHandler> handlers;

      if( !m_handlers.TryGetValue( routedEvent, out handlers ) )
      {
        handlers = new LinkedList<XceedRoutedEventHandler>();
        m_handlers.Add( routedEvent, handlers );
      }

      handlers.AddLast( handler );
    }

    internal void RemoveHandler( XceedRoutedEvent routedEvent, XceedRoutedEventHandler handler )
    {
      LinkedList<XceedRoutedEventHandler> handlers;

      if( m_handlers.TryGetValue( routedEvent, out handlers ) )
      {
        handlers.Remove( handler );
      }
    }

    internal static IXceedRoutedEventElement GetParent( IXceedRoutedEventElement element )
    {
      DependencyObject parent = VisualTreeHelper.GetParent( ( DependencyObject )element );

      while( ( parent != null ) && !( parent is IXceedRoutedEventElement ) )
        parent = VisualTreeHelper.GetParent( ( DependencyObject )parent );

      return ( IXceedRoutedEventElement )parent;
    }

    #region Private Fields

    private readonly Dictionary<XceedRoutedEvent, LinkedList<XceedRoutedEventHandler>> m_handlers = new Dictionary<XceedRoutedEvent, LinkedList<XceedRoutedEventHandler>>();
    private readonly IXceedRoutedEventElement m_element;

    #endregion
  }
}
